package com.alks.common.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class QRCodeGenerator {

    public static ByteArrayOutputStream generateQRCodeToStream(String text, int width, int height) throws WriterException, IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height);

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }

        ImageIO.write(image, "png", outputStream);

        return outputStream;
    }

    /**
     * 生成二维码,降低二维码的密度，以减少空白区域
     * @param text
     * @param width
     * @param height
     * @return
     * @throws WriterException
     * @throws IOException
     */
    public static ByteArrayOutputStream generateQRCodeWithText(String text, int width, int height, String labelText) throws WriterException, IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        // 设置二维码的容错级别为 H（最高容错级别）
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 增加容错级别
        hints.put(EncodeHintType.MARGIN, 0); // 可以设置二维码的白边，设置为0无白边

        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);

        // 创建二维码图片
        BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                qrImage.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFF); // 黑白二维码
            }
        }

        // 设置字体和文本区域的高度
        int fontSize = 20;
        int textHeight = fontSize + 3; // 文本区域高度

        // 创建一张新的图片，包含二维码和文本
        BufferedImage combinedImage = new BufferedImage(width, height + textHeight * 3, BufferedImage.TYPE_INT_RGB); // Text height increased for more lines
        Graphics2D g2d = combinedImage.createGraphics();

        // 背景填充为白色
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, width, height + textHeight * 3);

        // 在顶部绘制二维码
        g2d.drawImage(qrImage, 0, 0, null);

        // 设置文本属性
        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("Arial", Font.PLAIN, fontSize));

        // 计算文本的最大宽度
        FontMetrics fontMetrics = g2d.getFontMetrics();
        int maxLineWidth = width - 20; // 留出左右边距

        // 进行换行处理
        String[] lines = breakTextIntoLines(labelText, fontMetrics, maxLineWidth);

        // 计算文本绘制的起始位置
        int textY = height + fontSize; // 文本绘制在二维码下面
        for (String line : lines) {
            int textWidth = fontMetrics.stringWidth(line);
            int textX = (width - textWidth) / 2; // 文本水平居中
            g2d.drawString(line, textX, textY);
            textY += fontSize + 2; // 每行之间增加2个像素的间距
        }

        g2d.dispose();

        // 将图像写入输出流
        ImageIO.write(combinedImage, "png", outputStream);

        return outputStream;
    }

    // 根据最大宽度将文本拆分成多行
    private static String[] breakTextIntoLines(String text, FontMetrics fontMetrics, int maxLineWidth) {
        // 按空格切分单词，避免断裂
        String[] words = text.split("-");
        StringBuilder currentLine = new StringBuilder();
        List<String> lines = new ArrayList<>();

        for (String word : words) {
            // 判断加上当前单词后是否超出宽度限制
            if (fontMetrics.stringWidth(currentLine + word) <= maxLineWidth) {
                currentLine.append(word).append("-");
            } else {
                // 超出宽度，保存当前行并开始新的一行
                lines.add(currentLine.toString().trim());
                currentLine = new StringBuilder(word + "-");
            }
        }
        // 最后一个行
        if (currentLine.length() > 0) {
            String lastLine = currentLine.toString();
            // 去除最后一个 -
            if (lastLine.endsWith("-")) {
                lastLine = lastLine.substring(0, lastLine.length() - 1);
            }
            lines.add(lastLine);
        }

        return lines.toArray(new String[0]);
    }


    public static void main(String[] args) {
        try {
            String text = "https://www.baidu.com";
            int width = 170;
            int height = 170;

            ByteArrayOutputStream outputStream = generateQRCodeToStream(text, width, height);

            // Now you can use the outputStream to get the InputStream
            // InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
            String filePath = "qr_code.png";

            // 将 ByteArrayOutputStream 中的数据写入到文件
            FileOutputStream fileOutputStream = new FileOutputStream(filePath);
            outputStream.writeTo(fileOutputStream);
            fileOutputStream.close();
            System.out.println("文件已成功写入：" + filePath);

            System.out.println("QR Code generated successfully!");
        } catch (Exception e) {
            System.err.println("Error generating QR Code: " + e.getMessage());
        }
    }
}